package com.kmxd.ams.core.result;

import com.kmxd.ams.core.common.constant.Constants;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import lombok.ToString;
import org.slf4j.MDC;

import java.io.Serializable;
import java.util.Optional;

/**
 * 统一API响应结果封装
 *
 * @author admin
 */
@SuppressWarnings("ALL")
@Getter
@Setter
@ToString
@NoArgsConstructor
public class R<T> implements Serializable {

  private static final long serialVersionUID = 1L;

  /** 状态码 */
  private int code;
  /** 承载数据 */
  private T data;
  /** 传入参数 */
  private Object parameter;
  /** 返回消息 */
  private String msg;

  private String debugCode;
  private String debugMsg;

  private R(int code, T data, String msg) {
    this.code = code;
    this.data = data;
    this.msg = msg;
  }

  private R(int code, T data, Object parameter, String msg) {
    this.code = code;
    this.data = data;
    this.parameter = parameter;
    this.msg = msg;
  }

  private R(int code, T data, String msg, String debugCode, String debugMsg) {
    this.code = code;
    this.data = data;
    this.msg = msg;
    this.debugCode = debugCode;
    this.debugMsg =
        debugMsg + "【" + Optional.ofNullable(MDC.get(Constants.TRANCE_ID)).orElse("") + "】";
  }

  private R(IResultCode resultCode) {
    this(resultCode, null, resultCode.getMessage());
  }

  private R(IResultCode resultCode, T data) {
    this(resultCode, data, resultCode.getMessage());
  }

  private R(IResultCode resultCode, T data, Object parameter) {
    this(resultCode, data, parameter, resultCode.getMessage());
  }

  private R(IResultCode resultCode, String msg) {
    this(resultCode, null, msg);
  }

  private R(IResultCode resultCode, String msg, String debugCode, String debugMsg) {
    this(resultCode.getCode(), null, msg, debugCode, debugMsg);
  }

  private R(IResultCode resultCode, T data, String msg) {
    this(resultCode.getCode(), data, msg);
  }

  private R(IResultCode resultCode, T data, Object parameter, String msg) {
    this(resultCode.getCode(), data, parameter, msg);
  }

  public static <T> R<T> success() {
    return new R<>(ResultCode.SUCCESS);
  }

  public static <T> R<T> success(T data) {
    return new R<>(ResultCode.SUCCESS, data);
  }

  public static <T> R<T> success(T data, Object parameter) {
    return new R<>(ResultCode.SUCCESS, data, parameter);
  }

  public static <T> R<T> success(T data, String msg) {
    return new R<>(ResultCode.SUCCESS, data, msg);
  }

  public static <T> R<T> fail(String msg) {
    return new R<>(ResultCode.FAILURE, msg);
  }

  public static <T> R<T> fail(
      IResultCode resultCode, String msg, String debugCode, String debugMsg) {
    return new R<>(resultCode, msg, debugCode, debugMsg);
  }

  public static <T> R<T> result(IResultCode resultCode) {
    return new R<>(resultCode);
  }

  public static <T> R<T> result(IResultCode resultCode, T data) {
    return new R<>(resultCode, data);
  }

  public static <T> R<T> result(IResultCode resultCode, T data, String msg) {
    return new R<>(resultCode, data, msg);
  }

  public static <T> R<T> result(int code, String msg) {
    return new R<>(code, null, msg);
  }

  public static <T> R<T> result(int code, T data, String msg) {
    return new R<>(code, data, msg);
  }
}
